﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Imaging;
using System.Drawing;
using Team6_Algorithms.AidingClasses;

namespace Team6_Algorithms.HighEnd
{
    /// <summary>
    /// A class to perform some basic HSL operations (foremost a exclusion filter) to 
    /// an image.
    /// </summary>
    public class HsvFilter
    {

        private static Bitmap b;

        private static object [,] Points;

        /// <summary>
        /// This function will start an exclusion filter on the given image with the given parameters.
        /// the low parameters stand for the low treshold, and high parameters for the high treshold.
        /// This means that given a low of 30 and a high of 80, this function will exclude everthing outside 30 - 80.
        /// </summary>
        /// <param name="bitmap">The input image</param>
        /// <param name="HueLow">The low treshold for HUE. has to be between 0 - 360</param>
        /// <param name="HueHigh">The high treshold for HUE. has to be between 0 - 360</param>
        /// <param name="SaturationLow">the low treshold for saturation. has to be between 0 - 100</param>
        /// <param name="SaturationHigh">the high treshold for saturation. has to be between 0 - 100</param>
        /// <param name="lightnessLow">the low treshold for lightness. has to be between 0 - 100</param>
        /// <param name="LightnessHigh">the high treshold for lightness. has to be between 0 - 100</param>
        /// <returns></returns>
        public static bool startExclusionFilter(Bitmap bitmap, int HueLow, int HueHigh, int SaturationLow, int SaturationHigh, int lightnessLow, int LightnessHigh)
        {
            b = bitmap;

            BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
            ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = bmData.Stride;

            System.IntPtr Scan0 = bmData.Scan0;
            double waardeH, waardeS, waardeL;

            unsafe
            {
                byte* p = (byte*)(void*)Scan0;

                int nOffset = stride - b.Width * 3;

                byte Red, Green, Blue;

                for (int y = 0; y < b.Height; ++y)
                {
                    for (int x = 0; x < b.Width; ++x)
                    {

                        Red = p[2];
                        Green = p[1];
                        Blue = p[0];

                        Color color = Color.FromArgb(Red, Green, Blue);

                        RGB2HSL(color, out waardeH, out waardeS, out waardeL);

                        waardeH *= 360;
                        waardeS *= 100;
                        waardeL *= 100;

                        //If hue is tussen 50 - 70 graden { niets doen } anders { zwart maken }
                        if (!(waardeH > (double)HueLow && waardeH < (double)HueHigh))
                        {
                                p[0] = (byte)0;
                                p[1] = (byte)0;
                                p[2] = (byte)0;

                        }

                        if (waardeS < SaturationHigh)
                        {
                            p[0] = (byte)0;
                            p[1] = (byte)0;
                            p[2] = (byte)0;
                        } 
                        if (waardeL > lightnessLow)
                        {
                            p[0] = (byte)0;
                            p[1] = (byte)0;
                            p[2] = (byte)0;
                        } 


                        p += 3;
                    }
                    p += nOffset;
                }
            }
            b.UnlockBits(bmData); 
            return true;
        }

        /// <summary>
        /// Function to convert RGB format to HSL color space
        /// </summary>
        /// <param name="rgb">A color object for the color to be converted</param>
        /// <param name="h">Hue output</param>
        /// <param name="s">Saturation output</param>
        /// <param name="l">Lightness output</param>
        public static void RGB2HSL(Color rgb, out double h, out double s, out double l)
        {

            double r = rgb.R / 255.0;
            double g = rgb.G / 255.0;
            double b = rgb.B / 255.0;

            double v;
            double m;
            double vm;
            double r2, g2, b2;

            h = 0; // default to black
            s = 0;
            l = 0;

            v = Math.Max(r, g);
            v = Math.Max(v, b);
            m = Math.Min(r, g);
            m = Math.Min(m, b);
            l = (m + v) / 2.0;

            if (l <= 0.0)
            {
                return;
            }

            vm = v - m;
            s = vm;

            if (s > 0.0)
            {
                s /= (l <= 0.5) ? (v + m) : (2.0 - v - m);
            }
            else
            {
                return;
            }

            r2 = (v - r) / vm;
            g2 = (v - g) / vm;
            b2 = (v - b) / vm;

            if (r == v)
            {
                h = (g == m ? 5.0 + b2 : 1.0 - g2);
            }
            else if (g == v)
            {
                h = (b == m ? 1.0 + r2 : 3.0 - b2);
            }
            else
            {
                h = (r == m ? 3.0 + g2 : 5.0 - r2);
            }
            h /= 6.0;
        }

    }
}
